/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.jfonia.view.components;

import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Rectangle;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.plaf.basic.BasicButtonUI;
import javax.swing.plaf.basic.BasicGraphicsUtils;

/**
 * Credits to Ken (http://explodingpixels.wordpress.com/2009/12/02/creating-the-itunes-navigation-header-button/)
 * @author Rik Bauwens
 */
public class ITunesHeaderButtonUI extends BasicButtonUI {

    private static Color TEXT_COLOR = Color.WHITE;
    private static Color TEXT_SHADOW_COLOR = Color.BLACK;

    // the gradient colors for when the button is selected.
    private static Color SELECTED_BACKGROUND_COLOR_1 = new Color(0x141414);
    private static Color SELECTED_BACKGROUND_COLOR_2 = new Color(0x1e1e1e);
    private static Color SELECTED_BACKGROUND_COLOR_3 = new Color(0x191919);
    private static Color SELECTED_BACKGROUND_COLOR_4 = new Color(0x1e1e1e);

    // the border colors for the button.
    private static Color SELECTED_TOP_BORDER = new Color(0x030303);
    private static Color SELECTED_BOTTOM_BORDER = new Color(0x292929);

    // the border colors between buttons.
    private static Color LEFT_BORDER = new Color(255,255,255,21);
    private static Color RIGHT_BORDER = new Color(0,0,0,125);

    private static final Color SELECTED_INNER_SHADOW_COLOR_1 = new Color(0x161616);
    private static final Color SELECTED_INNER_SHADOW_COLOR_2 = new Color(0x171717);
    private static final Color SELECTED_INNER_SHADOW_COLOR_3 = new Color(0x191919);

    @Override
    protected void installDefaults(AbstractButton button) {
        super.installDefaults(button);
        button.setBackground(new Color(0,0,0,0));
        button.setOpaque(false);
    }

    @Override
    public void paint(Graphics g, JComponent c) {
        // if the button is selected, paint the special background now.
        // if it is not selected paint the left and right highlight border.
        AbstractButton button = (AbstractButton) c;
        if (button.isSelected()) {
            paintButtonSelected(g, button);
        } else {
            // paint the border and border highlight if the button isn't
            // selected.
            g.setColor(LEFT_BORDER);
            g.drawLine(0, 1, 0, button.getHeight()-2);
            g.setColor(RIGHT_BORDER);
            g.drawLine(button.getWidth()-1, 1,
                    button.getWidth()-1, button.getHeight()-2);
        }

        super.paint(g, c);
    }

    @Override
    protected void paintText(Graphics g, AbstractButton button,
                             Rectangle textRect, String text) {
        // we need to override the paintText method so that we can paint
        // the text shadow. the paintText method in BasicButtonUI pulls
        // the color to use from the foreground property -- there is no
        // way to change this during the painting process without causing
        // an infinite sequence of events, so we must implement our own
        // text painting.

        FontMetrics fontMetrics = g.getFontMetrics(button.getFont());
        int mnemonicIndex = button.getDisplayedMnemonicIndex();

        // paint the shadow text.
        g.setColor(TEXT_SHADOW_COLOR);
        BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex,
                textRect.x + getTextShiftOffset(),
                textRect.y + fontMetrics.getAscent() + getTextShiftOffset() - 1);

        // paint the actual text.
        g.setColor(TEXT_COLOR);
        BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex,
                textRect.x + getTextShiftOffset(),
                textRect.y + fontMetrics.getAscent() + getTextShiftOffset());
    }

    /**
     * Paints the selected buttons state, also used as the pressed state.
     */
    private void paintButtonSelected(Graphics graphics, AbstractButton button) {
        // calculate the middle of the area to paint.
        int midY = button.getHeight()/2;

        Paint topPaint = new GradientPaint(0, 0, SELECTED_BACKGROUND_COLOR_1,
                0, midY, SELECTED_BACKGROUND_COLOR_2);
        ((Graphics2D) graphics).setPaint(topPaint);
        graphics.fillRect(0, 0, button.getWidth(), midY);

        // paint the top half of the background with the corresponding
        // gradient.
        Paint bottomPaint =
                new GradientPaint(0, midY + 1, SELECTED_BACKGROUND_COLOR_3,
                        0, button.getHeight(), SELECTED_BACKGROUND_COLOR_4);
        ((Graphics2D) graphics).setPaint(bottomPaint);
        graphics.fillRect(0, midY, button.getWidth(), button.getHeight());

        // draw the top and bottom border.
        graphics.setColor(SELECTED_TOP_BORDER);
        graphics.drawLine(0, 0, button.getWidth(), 0);
        graphics.setColor(SELECTED_BOTTOM_BORDER);
        graphics.drawLine(0, button.getHeight() - 1,
                button.getWidth(), button.getHeight() - 1);

        // paint the outter part of the inner shadow.
        graphics.setColor(SELECTED_INNER_SHADOW_COLOR_1);
        graphics.drawLine(0, 1, 0, button.getHeight()-2);
        graphics.drawLine(0, 1, button.getWidth(), 1);
        graphics.drawLine(button.getWidth()-1, 1,
                button.getWidth()-1, button.getHeight()-2);

        // paint the middle part of the inner shadow.
        graphics.setColor(SELECTED_INNER_SHADOW_COLOR_2);
        graphics.drawLine(1, 1, 1, button.getHeight()-2);
        graphics.drawLine(0, 2, button.getWidth(), 2);
        graphics.drawLine(button.getWidth()-2, 1,
                button.getWidth()-2, button.getHeight()-2);

        // paint the inner part of the inner shadow.
        graphics.setColor(SELECTED_INNER_SHADOW_COLOR_3);
        graphics.drawLine(2, 1, 2, button.getHeight()-2);
        graphics.drawLine(0, 3, button.getWidth(), 3);
        graphics.drawLine(button.getWidth()-3, 1,
                button.getWidth()-3, button.getHeight()-2);
    }

    @Override
    protected void paintButtonPressed(Graphics graphics, AbstractButton button) {
        paintButtonSelected(graphics, button);
    }
}
